#include "../include/BusinessService.hpp"
#include "../include/MySQLClient.hpp"
#include "../include/Mylogger.hpp"
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>



// BusinessService.cc 补充实现
struct RecordRequest {
    string cameraId;
    string startTime; // 格式: "YYYY-MM-DD HH:MM:SS"
    string endTime;
};


// 在 BusinessService.cc 的开头添加 parseRequest 函数
RecordRequest parseRequest(const string& msg) {
    RecordRequest req;

    // 假设消息格式为: "cameraId|startTime|endTime"
    // 例如: "1|2025-08-19 10:00:00|2025-08-19 12:00:00"

    size_t pos1 = msg.find('|');
    if (pos1 != string::npos) {
        req.cameraId = msg.substr(0, pos1);

        size_t pos2 = msg.find('|', pos1 + 1);
        if (pos2 != string::npos) {
            req.startTime = msg.substr(pos1 + 1, pos2 - pos1 - 1);
            req.endTime = msg.substr(pos2 + 1);
        } else {
            // 如果只有两个部分，可能是 "cameraId|startTime"
            req.startTime = msg.substr(pos1 + 1);
            req.endTime = ""; // 结束时间为空
        }
    } else {
        // 如果没有分隔符，整个消息作为cameraId
        req.cameraId = msg;
        req.startTime = "";
        req.endTime = "";
    }

    printf("解析----------------\n");
    cout << req.cameraId << endl;
    cout << req.startTime << endl;
    cout << req.endTime << endl;

    return req;
}



//处理用户登录发送的用户名
void UserLoginSection1::process(){


    wd::MySQLClient _mysql;
    bool ret = _mysql.connect("127.0.0.1", 3306, "root", "1234",
                              "3th");
    if(ret){
        cout << "login1  mysql has connectioned" << endl;
    }else{
        cout << "mysql connection error" << endl;
        //发送sendInLoop(error)
    }

    if(_packet.type == wd::TASK_TYPE_LOGIN_SECTION1){

        string username = _packet.msg;  //获取用户名
        cout << "username: " << username << endl;


        //执行查询select操作
        string sql = "SELECT id, name, setting, encrypt FROM user WHERE name = '" + username + "'";
        //查询结果放在res中
        vector<vector<string>>res = _mysql.readOperationQuery(sql);


        //1.判断用户名是否存在于数据库中

        if(res.size() < 1){ 
            //2.用户名不存在数据库中，回复ERROR,
            //即TLV.type = TASK_TYPE_LOGIN_SECTION1_RESP_ERROR
            LOG_ERROR(username + "用户未注册,请注册");
            wd::TLV tlv;
            tlv.type = wd::TASK_TYPE_LOGIN_SECTION1_RESP_ERROR;
            tlv.length = 0;//不需要发送消息体了
            _conn->sendInLoop(tlv);
            return;
        }else{

            //3.如果存在，从数据库中取出盐值发送给客户端
            //TLV.type = TASK_TYPE_LOGIN_SECTION1_RESP_OK;
            LOG_ERROR(username + "用户已注册,发送salt");

            //4.保存用户名，后续查询使用
            _conn->setUsername(username);


            //5.将setting发给客户端
            string setting = res[1][2];  //盐值存放在res[1][2]中

            wd::TLV tlv;
            tlv.type = wd::TASK_TYPE_LOGIN_SECTION1_RESP_OK;
            tlv.length = setting.length();
            strncpy(tlv.data, setting.c_str(), tlv.length);
            _conn->sendInLoop(tlv);
        }


    }

}



//处理用户发送的加密密码
void UserLoginSection2::process(){

    wd::MySQLClient _mysql;
    bool ret = _mysql.connect("127.0.0.1", 3306, "root", "1234",
                              "3th");
    if(ret){
        cout << "login2  mysql has connectioned" << endl;
    }else{
        cout << "mysql connection error" << endl;
        //发送sendInLoop(error)
    }

    if(_packet.type == wd::TASK_TYPE_LOGIN_SECTION2){

        //客户端发来的加密密码
        string passwd = _packet.msg;
        string username = _conn->getUsername();

        //执行查询select操作
        string sql = "SELECT id, name, setting, encrypt FROM user WHERE name = '" + username + "'";
        //查询结果放在res中
        vector<vector<string>>res = _mysql.readOperationQuery(sql);

        //判断查询是否成功
        if(res.size() < 1){
            //查询失败
            return;
        }


        //比对密码
        if(res[1][3] == passwd){
            //登录成功
            LOG_ERROR(username + "登录成功");
            wd::TLV tlv;
            tlv.type = wd::TASK_TYPE_LOGIN_SECTION2_RESP_OK;
            tlv.length = 0; 
            _conn->sendInLoop(tlv);

        }else{
            //登录失败
            LOG_ERROR(username + "登录失败");
            wd::TLV tlv;
            tlv.type = wd::TASK_TYPE_LOGIN_SECTION2_RESP_ERROR;
            tlv.length = 0; 
            _conn->sendInLoop(tlv);
        }

    }

}



//注册1
void UserRegisterSection1::process(){

    // 连接数据库
    wd::MySQLClient _mysql;
    bool ret = _mysql.connect("127.0.0.1", 3306, "root", "1234", "3th");
    if (!ret) {
        cout << "数据库连接失败" << endl;
        wd::TLV tlv;
        tlv.type = wd::TASK_TYPE_REGISTER1_RESP_ERROR;
        tlv.length = 0;
        _conn->sendInLoop(tlv);
        return;
    }

    if (_packet.type == wd::TASK_TYPE_REGISTER1) {
        string username = _packet.msg;

        // 检查用户名是否已存在
        string checkSql = "SELECT name FROM user WHERE name = '" + username + "'";
        vector<vector<string>> res = _mysql.readOperationQuery(checkSql);



        if (res.size() > 1) { // 用户名已存在
            LOG_INFO(username + "用户名已存在，请登录");
            wd::TLV tlv;
            tlv.type = wd::TASK_TYPE_REGISTER1_RESP_ERROR;
            tlv.length = 0;
            _conn->sendInLoop(tlv);
        } else {
            // 生成随机盐值
            string salt = "salt" + std::to_string(rand() % 10000);

            // 保存用户名，供第二阶段使用
            _conn->setUsername(username);

            // 发送盐值给客户端
            wd::TLV tlv;
            tlv.type = wd::TASK_TYPE_REGISTER1_RESP_OK;
            tlv.length = salt.length();
            strncpy(tlv.data, salt.c_str(), tlv.length);
            _conn->sendInLoop(tlv);

            LOG_INFO("已向 " + username + "发送setting");
        }
    }

}


// 处理用户注册第二阶段（密码存储）
void UserRegisterSection2::process() {

    // 连接数据库
    wd::MySQLClient _mysql;
    bool ret = _mysql.connect("127.0.0.1", 3306, "root", "1234", "3th");
    if (!ret) {
        cout << "数据库连接失败" << endl;
        wd::TLV tlv;
        tlv.type = wd::TASK_TYPE_REGISTER2_RESP_ERROR;
        tlv.length = 0;
        _conn->sendInLoop(tlv);
        return;
    }

    if (_packet.type == wd::TASK_TYPE_REGISTER2) {
        string encryptedPassword = _packet.msg;  // 格式: $1$salt$hash
        string username = _conn->getUsername();

        if (username.empty()) {
            LOG_ERROR("TcpConnection中未设置用户名");
            wd::TLV tlv;
            tlv.type = wd::TASK_TYPE_REGISTER2_RESP_ERROR;
            tlv.length = 0;
            _conn->sendInLoop(tlv);
            return;
        }

        // 从加密密码中提取salt部分
        size_t saltStart = encryptedPassword.find("$1$") + 3;
        size_t saltEnd = encryptedPassword.find('$', saltStart);

        if (saltStart == string::npos || saltEnd == string::npos) {
            LOG_WARN("无效的加密密码格式");
        }

        string salt = encryptedPassword.substr(saltStart, saltEnd - saltStart);

        // 执行插入操作，同时存储salt和encryptedPassword
        string insertSql = "INSERT INTO user (name, setting, encrypt) VALUES ('" +
            username + "', '" + salt + "', '" + encryptedPassword + "')";

        if (_mysql.writeOperationQuery(insertSql)) {
            LOG_INFO("用户注册成功" + username);
            LOG_INFO("加密的密码" + encryptedPassword);

            wd::TLV tlv;
            tlv.type = wd::TASK_TYPE_REGISTER2_RESP_OK;
            tlv.length = 0;
            _conn->sendInLoop(tlv);
        } else {
            LOG_INFO("用户注册失败");
            wd::TLV tlv;
            tlv.type = wd::TASK_TYPE_REGISTER2_RESP_ERROR;
            tlv.length = 0;
            _conn->sendInLoop(tlv);
        }
    }

}



//用户获取播放列表

void UserGetCameraList::process(){

    // 连接数据库
    wd::MySQLClient _mysql;
    bool ret = _mysql.connect("127.0.0.1", 3306, "root", "1234", "3th");
    if (!ret) {
        cout << "数据库连接失败" << endl;
        wd::TLV tlv;
        tlv.type = wd::TASK_TYPE_GET_CAMERALIST_RESP_ERROR;
        tlv.length = 0;
        _conn->sendInLoop(tlv);
        return;
    }

    if(_packet.type == wd::TASK_TYPE_GET_CAMERALIST){


        string numSql = "SELECT COUNT(*) FROM device";
        vector<vector<string>> numres = _mysql.readOperationQuery(numSql);
        int num = std::stoi(numres[1][0]);

        // 查询设备表
        string Sql = "SELECT camera_id,type FROM device";

        vector<vector<string>> res = _mysql.readOperationQuery(Sql);

        cout << num << endl;
        for(int i = 1; i < num + 1; ++i){
            cout<<i<<endl;
            wd::TLV tlv;
            if(res[i][1] == "0"){
                LOG_INFO("获得0号设备");
                tlv.type = wd::TASK_TYPE_GET_CAMERALIST_RESP_0;
                tlv.length = res[i][0].length();
                strncpy(tlv.data, res[i][0].c_str(), tlv.length);
                _conn->sendInLoop(tlv);
            }else{
                LOG_INFO("获得1号设备");
                tlv.type = wd::TASK_TYPE_GET_CAMERALIST_RESP_1;
                tlv.length = res[i][0].length();
                strncpy(tlv.data, res[i][0].c_str(), tlv.length);
                _conn->sendInLoop(tlv);

                cout<<"2end"<<i<<endl;
            }

        }
    }

    return; 
}


//发送RTSP流给客户端
void UserGetRTSP::process(){

#if 0
    //音视频封装(容器)格式上下文结构体
    AVFormatContext * pFormatCtx = nullptr;
    pFormatCtx = avformat_alloc_context();

    //设置网络传输的传输层协议
    AVDictionary *avdic = nullptr;
    char option_key[] = "rtsp_transport";
    char option_value[] = "udp";
    av_dict_set(&avdic,option_key,option_value,0);

    char option_key2[] = "max_delay";
    char option_value2[] = "100";
    av_dict_set(&avdic,option_key2,option_value2,0);

    //实时流视频网络地址
    string url("rtsp://admin:admin@192.168.5.222/live/chn=0");

    //初始化FFmpeg网络模块
    avformat_network_init();

#endif
    wd::MySQLClient _mysql;
    bool ret = _mysql.connect("127.0.0.1", 3306, "root", "1234", "3th");
    if (!ret) {
        cout << "数据库连接失败" << endl;
        wd::TLV tlv;
        tlv.type = wd::TASK_TYPE_GET_CAMERALIST_RESP_ERROR;
        tlv.length = 0;
        _conn->sendInLoop(tlv);
        return;
    }

    string id_msg = _packet.msg;
    cout << "camera_id: " << id_msg << endl;

    // 查询设备表
    string Sql = "SELECT rtsp FROM device WHERE camera_id =  " + id_msg;

    vector<vector<string>> res = _mysql.readOperationQuery(Sql);

    _mysql.dump(res);

    if(res.empty() ||res.size() < 2){
        printf("no camera_id\n");
        return;
    }

    //从数据库中获取到rtsp
    string url = res[1][0];
    cout << url << "--------" << endl;
    init();

    ret = avformat_open_input(&pFormatCtx,url.data(),nullptr,&avdic);
    if(ret != 0){
        perror("avformat_open_input");
        return;
    }
    printf("open avformat_open_input success\n");

#if 1

    if (avformat_find_stream_info(pFormatCtx, nullptr) < 0)
    {
        printf("open stream information filed\n");
        return;
    }

    av_dump_format(pFormatCtx,0,"RTSP",0);




    // 查找视频流
    int video_stream_idx = -1;
    for (unsigned int i = 0; i < pFormatCtx->nb_streams; i++) {
        if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
            video_stream_idx = i;
            break;
        }
    }

    if (video_stream_idx == -1) {
        cerr << "No video stream found" << endl;
        avformat_close_input(&pFormatCtx);
    }


    AVStream* video_stream = pFormatCtx->streams[video_stream_idx];
    AVCodecParameters* codecpar = video_stream->codecpar;

    // 打印视频流信息
    cout << "\nVideo Stream Information:" << endl;
    cout << "  Codec: " << avcodec_get_name(codecpar->codec_id) << endl;
    cout << "  Resolution: " << codecpar->width << "x" << codecpar->height << endl;
    cout << "  Framerate: " << av_q2d(video_stream->avg_frame_rate) << " fps" << endl;

#endif

    // 开始读取包
    AVPacket* pkt = av_packet_alloc();
    if (!pkt) {
        cerr << "Failed to allocate packet" << endl;
        avformat_close_input(&pFormatCtx);
    }


    while (1) {


        if (av_read_frame(pFormatCtx, pkt) < 0) {

            break; //这里认为视频读取完了
        }
        printf("3th\n");

        if(pkt->stream_index == video_stream_idx){
#if 1
            wd::TVLPacket tlv;
            tlv.type = wd::TASK_TYPE_GET_PACKET_OK;
            tlv.length = pkt->size + 4;
            tlv.camera_id = std::stoi(_packet.msg);
            tlv.data.assign(reinterpret_cast<const char*>(pkt->data), pkt->size);

            // 构造完整的消息字符串
            string msg;
            msg.append(reinterpret_cast<const char*>(&tlv.type), sizeof(tlv.type));
            msg.append(reinterpret_cast<const char*>(&tlv.length), sizeof(tlv.length));
            msg.append(reinterpret_cast<const char*>(&tlv.camera_id), sizeof(tlv.camera_id));
            
            msg.append(tlv.data);

            // 调用string版本
            _conn->sendInLoop(msg);  // 这会调用 void TcpConnection::sendInLoop(const string& msg)
                                     //将Packet发给客户端
            printf("----sendPacket to client\n");

#endif
        }else{
            printf("sendPacket error\n");
        }

        av_packet_unref(pkt);
    }


    // 清理资源
    av_packet_free(&pkt);
    av_dict_free(&avdic);
    avformat_close_input(&pFormatCtx);

}



//------------------


// 处理客户端录像请求
void UserGetRecordings::process() {
    wd::MySQLClient mysql;
    if (!mysql.connect("127.0.0.1", 3306, "root", "1234", "3th")) {
        LOG_ERROR("数据库连接失败");
        return;
    }

    cout << "---------Video---" << _packet.msg << endl;


#if 1
    // 解析客户端请求 (camera_id, start_time, end_time)
    RecordRequest req = parseRequest(_packet.msg);
    

#if 0
    // 查询符合条件的录像
    string sql = "SELECT camera_id, name, start_time, end_time, path FROM videoRecord "
                 "WHERE camera_id = '" + req.cameraId + "' "
                 "AND start_time >= '" + req.startTime + "' "
                 "AND end_time <= '" + req.endTime + "'";

#endif

    string sql = "SELECT id, name, start_time, end_time, path FROM videoRecord "
             "WHERE camera_id = '" + req.cameraId + "' "
             "AND start_time <= '" + req.endTime + "' "  // 录像开始时间不晚于查询结束时间
             "AND end_time >= '" + req.startTime + "'"; // 录像结束时间不早于查询开始时间

    vector<vector<string>> res = mysql.readOperationQuery(sql);

    mysql.dump(res);
    
    if (res.size() <= 1) {
        LOG_INFO("未找到符合条件的录像");
        return;
    }

    // 发送录像列表或直接发送录像数据
    for (size_t i = 1; i < res.size(); ++i) {
        string path = res[i][4]; // 路径在第5列
        sendRecordingFile(path);
    }

#endif

}

// 发送录像文件(以AVPacket形式)
void UserGetRecordings::sendRecordingFile(const string& path) {
    AVFormatContext* fmtCtx = nullptr;
    if (avformat_open_input(&fmtCtx, path.c_str(), nullptr, nullptr) < 0) {
        LOG_ERROR("无法打开录像文件: " + path);
        return;
    }

    if (avformat_find_stream_info(fmtCtx, nullptr) < 0) {
        LOG_ERROR("无法获取录像文件信息");
        avformat_close_input(&fmtCtx);
        return;
    }

    // 查找视频流
    int videoStream = -1;
    for (unsigned int i = 0; i < fmtCtx->nb_streams; i++) {
        if (fmtCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
            videoStream = i;
            break;
        }
    }

    if (videoStream == -1) {
        LOG_ERROR("录像文件中未找到视频流");
        avformat_close_input(&fmtCtx);
        return;
    }

    // 读取并发送AVPacket
    AVPacket *pkt = av_packet_alloc();
    pkt->data = nullptr;
    pkt->size = 0;

    while (av_read_frame(fmtCtx, pkt) >= 0) {
        if (pkt->stream_index == videoStream) {
            // 封装成自定义TLV格式发送
            sendAVPacketAsTLV(*pkt);
        }
        av_packet_unref(pkt);
    }

    avformat_close_input(&fmtCtx);
}



void UserGetRecordings::sendAVPacketAsTLV(const AVPacket& pkt) {

    // 解析摄像头ID
    uint32_t camera_id = std::stoi(_packet.msg);

    // 直接构造消息（完全模仿UserGetRTSP的方式）
    std::string msg;

    // 1. 添加类型字段
    uint32_t type = wd::TASK_TYPE_GET_VIDEO_OK;
    msg.append(reinterpret_cast<const char*>(&type), sizeof(type));

    // 2. 添加长度字段（数据大小 + PTS + 数据长度字段）
   // uint32_t length = pkt.size + sizeof(int64_t) + sizeof(int);
    uint32_t length = pkt.size  + sizeof(int);
    msg.append(reinterpret_cast<const char*>(&length), sizeof(length));

    // 4. 添加PTS时间戳
   // int64_t pts = pkt.pts;
   // msg.append(reinterpret_cast<const char*>(&pts), sizeof(pts));

    // 5. 添加数据大小
    /* int data_size = pkt.size; */
    /* msg.append(reinterpret_cast<const char*>(&data_size), sizeof(data_size)); */


    // 3. 添加摄像头ID字段
    msg.append(reinterpret_cast<const char*>(&camera_id), sizeof(camera_id));



    // 6. 添加实际的视频数据
    msg.append(reinterpret_cast<const char*>(pkt.data), pkt.size);

    // 发送给客户端
    _conn->sendInLoop(msg);

    LOG_INFO("发送视频包: 类型=" + std::to_string(type) +
              ", 长度=" + std::to_string(length) +
              ", 摄像头=" + std::to_string(camera_id));
}

#if 0
// 将AVPacket封装成TLV格式发送
void UserGetRecordings::sendAVPacketAsTLV(const AVPacket& pkt) {
    wd::TLV tlv;
    tlv.type = wd::TASK_TYPE_GET_VIDEO_OK;
    tlv.length = pkt.size + sizeof(int64_t) + sizeof(int); // 包含PTS和大小

    // 分配缓冲区
    char* data = new char[tlv.length];
    int pos = 0;

    // 写入PTS
    memcpy(data + pos, &pkt.pts, sizeof(int64_t));
    pos += sizeof(int64_t);

    // 写入数据大小
    memcpy(data + pos, &pkt.size, sizeof(int));
    pos += sizeof(int);

    // 写入数据
    memcpy(data + pos, pkt.data, pkt.size);

    // 发送
    memcpy(tlv.data, data, tlv.length);
    _conn->sendInLoop(tlv);

    delete[] data;
}

#endif
